#include <iostream>
#include <vector>
#include <functional>
#include <unistd.h>
#include <sys/wait.h>
#include "Task.hpp"
#include "Channel.hpp"

using work_t = std::function<void()>;

enum
{
    OK,
    INPUTERROR,
    PIPEERROR,
    FORKERROR,
};

class processpool
{
public:
    processpool(int num, work_t w)
        : processnum(num), work(w)
    {
    }
    // channls: 输出型参数
    // work_t work: 回调函数
    int InitProcessPool()
    {
        for (int i = 0; i < processnum; i++)
        {
            int pipefd[2] = {0};
            int fd = pipe(pipefd);
            if (fd < 0)
                return PIPEERROR;

            pid_t id = fork();
            if (id < 0)
                return FORKERROR;
            // 建立通信信道
            if (id == 0)
            {
                for(auto e: channels)
                {
                    std::cout << "关闭的历史写端：" << e.Wfd();
                    ::close(e.Wfd());
                }
                std::cout << std::endl;
                // 子进程
                ::close(pipefd[1]);
                // 未来读命令从键盘读
                dup2(pipefd[0], 0);
                // 执行任务
                work();
                // 退出
                ::exit(0);
            }
            // 父进程
            ::close(pipefd[0]);
            channels.emplace_back(pipefd[1], id);
            // channel ch(pipefd[1],id);
            // channels.push_back(ch);
        }
        return OK;
    }

    void DispatchTask()
    {
        int who = 0;
        // 2.派发任务
        int num = 20;
        while (num--)
        {
            // a.选择一个任务
            int task = ts.SelectTask();
            // b.选择一个子进程
            channel &curr = channels[who++];
            who %= channels.size();
            std::cout << "############################" << std::endl;
            std::cout << "send " << task << " to " << curr.Name() << "任务还剩：" << num << std::endl;
            std::cout << "############################" << std::endl;
            sleep(1);
            // c.派发任务
            curr.Send(task);
        }
    }

    void ExitProcess()
    {
        for (auto e : channels)
        {
            e.Close();
            int rid = ::waitpid(e.Id(), nullptr, 0);
            if (rid > 0)
            {
                std::cout << rid << "退出成功" << std::endl;
            }
        }

        // for (auto e : channels)
        // {
        //     e.Close();
        // }
        // for (auto e : channels)
        // {
        //     int rid = ::waitpid(e.Id(), nullptr, 0);
        //     if (rid > 0)
        //     {
        //         std::cout << rid << "退出成功" << std::endl;
        //     }
        // }
    }

    void DebugPrint()
    {
        for (auto &e : channels)
        {
            std::cout << e.Name() << std::endl;
        }
    }
    ~processpool()
    {
    }

private:
    int processnum;
    std::vector<channel> channels;
    work_t work;
};
